﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.IO;

namespace BingDesktopChanger.Forms
{

    public partial class frmViewer : Form
    {

        private enum FormAction
        {
            ShowingImages,
            LoadingImages,
            ShowingError
        }

        public frmViewer()
        {
            InitializeComponent();
            this.fileManager = new FileImageManager();
            this.manager = new DBImageManager(this.fileManager);
            this.retriever = new ImageReader(this.manager);
            this.retriever.StatusChanged += new NotifyStatusDelegate(this.retriever_StatusChanged);
        }


        private string[] imageList;
        private IImageManager manager;
        private FileImageManager fileManager;
        private ImageReader retriever;
        private bool formShown;
        private int currentImageIndex = 0;

        private void ChangeCurrentDate(DateTime targetDateTime, bool force)
        {
            this.dtpTargetDate.Value = targetDateTime;
            this.SetMessageInfo(FormAction.LoadingImages);
            bool loadImagesFromInternet = false;
            if (force)
            {
                this.manager.DeleteImages(targetDateTime);
                loadImagesFromInternet = true;
            }
            else
                if (!this.manager.ExistsDayImages(targetDateTime))
                    loadImagesFromInternet = true;
            if (loadImagesFromInternet)
                this.bgkWorker.RunWorkerAsync(targetDateTime);
            else
                this.LoadImagesSucceded();
        }
        private void LoadImagesSucceded()
        {
            this.imageList = this.manager.GetImageList(this.dtpTargetDate.Value);
            this.SetMessageInfo(FormAction.ShowingImages);
            if (this.imageList.Length > 0)
            {
                this.SetImage(0);
                this.pnlImages.Visible = true;
            }
            else
                this.pnlImages.Visible = false;
        }
        private void SetImage(int imageIndex)
        {
            this.picImage.ImageLocation = this.fileManager.GenerateImageFullPath(this.imageList[imageIndex]);
            if (File.Exists(this.picImage.ImageLocation))
            {
                this.picImage.Load();
                this.picImage.Visible = true;
            }
            else
                this.picImage.Visible = false;

            this.currentImageIndex = imageIndex;
            if (this.imageList.Length == 1)
                this.tslText.Visible = false;
            else
            {
                this.tslText.Text = string.Format("Imagen {0} de {1}", imageIndex + 1, this.imageList.Length);
                this.tslText.Visible = true;
            }
            this.tsbImgPrev.Enabled = (this.currentImageIndex > 0);
            this.tsbImgNext.Enabled = (this.currentImageIndex < this.imageList.Length - 1);
            this.tsbDelete.Enabled = this.tsbSetWallPaper.Enabled = (this.currentImageIndex > 0 && this.picImage.Visible);

        }
        private void SetMessageInfo(FormAction action)
        {
            this.pnlImages.Visible = false;
            this.pnlErrors.Visible = false;
            this.pnlWorking.Visible = false;
            switch (action)
            {
                case FormAction.ShowingImages:
                    this.pnlImages.Visible = true;
                    this.pnlImages.BringToFront();
                    this.UseWaitCursor = false;
                    break;
                case FormAction.LoadingImages:
                    this.UseWaitCursor = true;
                    this.pgbStatus.Style = ProgressBarStyle.Marquee;
                    this.pnlWorking.Visible = true;
                    break;
                case FormAction.ShowingError:
                    this.UseWaitCursor = false;
                    this.pnlErrors.Visible = true;
                    break;
            }
            this.Refresh();
        }

        #region Event Handlers
        private void bgkWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = this.retriever.ReadDayImages((DateTime)e.Argument);
        }
        private void bgkWorker_ProgressChanged(object sender, ProgressChangedEventArgs ex)
        {
            StatusNotificationEventArgs e = (StatusNotificationEventArgs)ex.UserState;
            if (e.StatusCode == StatusCode.GettingImage)
            {
                if (e.CurrentImageIndex == 1)
                {
                    this.pgbStatus.Style = ProgressBarStyle.Continuous;
                    this.pgbStatus.Maximum = e.ImagesCount;
                    this.pgbStatus.Value = 1;
                    this.lblStepInfo.Visible = true;
                }
                else
                    this.pgbStatus.PerformStep();
                this.lblMainStep.Text = e.StatusText;
                this.lblStepInfo.Text = string.Format("Obteniendo imágen {0}. ({1} de {2})",
                    e.CurrentImageName, e.CurrentImageIndex, e.ImagesCount);
            }
            else
                this.lblMainStep.Text = e.StatusText;
            this.pnlWorking.Refresh();
        }
        private void bgkWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((bool)e.Result && e.Error == null)
                this.LoadImagesSucceded();
            else
                this.SetMessageInfo(FormAction.ShowingError);
        }
        private void cmdUpgrade_Click(object sender, EventArgs e)
        {
            using (frmUpgrade fu = new frmUpgrade())
                fu.ShowDialog(this);
        }
        private void dtpTargetDate_CloseUp(object sender, EventArgs e)
        {
            if (this.formShown && !this.dtpTargetDate.Value.Equals(this.dtpTargetDate.Tag))
                this.tmrChange.Enabled = true;
        }
        private void dtpTargetDate_Enter(object sender, EventArgs e)
        {
            this.dtpTargetDate.Tag = this.dtpTargetDate.Value;
        }
        private void dtpTargetDate_Leave(object sender, EventArgs e)
        {
            if (this.formShown)
                if (!this.dtpTargetDate.Value.Equals(this.dtpTargetDate.Tag))
                    this.ChangeCurrentDate(this.dtpTargetDate.Value, false);
        }
        private void frmViewer_Load(object sender, EventArgs e)
        {
            this.Visible = false;
            this.pbInformation.Image = Bitmap.FromHicon(SystemIcons.Information.Handle);
            this.Location = new Point(
                Screen.PrimaryScreen.WorkingArea.Width - this.Width,
                Screen.PrimaryScreen.WorkingArea.Height - this.Height);
            this.dtpTargetDate.Value = DateTime.Today;
            this.dtpTargetDate.MaxDate = DateTime.Today;
            this.Visible = true;
            this.picError.Image = Bitmap.FromHicon(SystemIcons.Error.Handle);
        }
        private void frmViewer_Shown(object sender, EventArgs e)
        {
            this.formShown = true;
            this.ChangeCurrentDate(DateTime.Today, false);
        }
        private void picImage_DoubleClick(object sender, EventArgs e)
        {
            WallPaperChanger.Set(new Uri(this.picImage.ImageLocation), WallPaperChanger.Style.Stretched);
        }
        private void retriever_StatusChanged(object sender, StatusNotificationEventArgs e)
        {
            this.bgkWorker.ReportProgress(0, e);
        }
        private void tmrChange_Tick(object sender, EventArgs e)
        {
            this.tmrChange.Enabled = false;
            this.ChangeCurrentDate(this.dtpTargetDate.Value, false);
        }
        private void tsbSetWallPaper_Click(object sender, EventArgs e)
        {
            WallPaperChanger.Set(new Uri(this.picImage.ImageLocation), WallPaperChanger.Style.Stretched);

        }
        private void tsbImgNext_Click(object sender, EventArgs e)
        {
            this.SetImage(this.currentImageIndex + 1);
        }
        private void tsbDelete_Click(object sender, EventArgs e)
        {
            this.manager = new FileImageManager();
            this.manager.DeleteImage(this.picImage.ImageLocation);
            this.LoadImagesSucceded();
        }
        private void tsbRefresh_Click(object sender, EventArgs e)
        {
            this.ChangeCurrentDate(this.dtpTargetDate.Value, true);
        }
        private void tsbImgPrev_Click(object sender, EventArgs e)
        {
            this.SetImage(this.currentImageIndex - 1);
        }
        #endregion
    }
}
